package com.li.springbootproject.designpatterns.template;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author LiDong
 * @version 1.0.0
 * @createTime 4/3/2022 12:24 PM
 */
public abstract class MyJdbcTemplate {

    private static final Logger logger = LoggerFactory.getLogger(MyJdbcTemplate.class);

    /**
     * 数据源
     */
    private final DataSource dataSource;

    /**
     * 构造方法初始化 dataSource
     *
     * @param dataSource 数据源
     */
    public MyJdbcTemplate(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    /**
     * Jdbc Sql 查询过程
     *
     * @param sql    sql
     * @param values values
     * @return List
     */
    public final List<?> executeQuery(String sql, Object[] values) {
        try {
            Connection connection = this.getConnection();
            PreparedStatement pre = this.createPrepareStatement(connection, sql);
            ResultSet resultSet = this.executeQuery(pre, values);
            List<Object> result = new ArrayList<>();
            while (resultSet.next()) {
                result.add(rowMapper(resultSet));
            }
            resultSet.close();
            pre.close();
            connection.close();
            return result;
        } catch (Exception exception) {
            logger.error("Error occurred :", exception);
        }
        return null;
    }

    /**
     * 由子类实现
     *
     * @param resultSet
     * @return
     * @throws SQLException
     */
    protected abstract Object rowMapper(ResultSet resultSet) throws SQLException;

    /**
     * 执行查询
     *
     * @param preparedStatement preparedStatement
     * @param values            values
     * @return ResultSet
     * @throws SQLException
     */
    private ResultSet executeQuery(PreparedStatement preparedStatement, Object[] values) throws SQLException {
        for (int i = 0; i < values.length; i++) {
            preparedStatement.setObject(i, values[i]);
        }
        return preparedStatement.executeQuery();
    }

    /**
     * 对 SQL 语句进行预编译的操作
     *
     * @param connection connection
     * @param sql        sql
     * @return PreparedStatement
     * @throws SQLException
     */
    private PreparedStatement createPrepareStatement(Connection connection, String sql) throws SQLException {
        return connection.prepareStatement(sql);
    }

    /**
     * 获取连接
     *
     * @return Connection
     * @throws SQLException
     */
    private Connection getConnection() throws SQLException {
        return this.dataSource.getConnection();
    }


}
